home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / xlib / cmapfog.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  11KB  |  410 lines

  1. /*
  2.  * Copyright (c) 1995, Silicon Graphics, Inc.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee, provided
  6.  * that the name of Silicon Graphics may not be used in any advertising or
  7.  * publicity relating to the software without the specific, prior written
  8.  * permission of Silicon Graphics.
  9.  *
  10.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  11.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  12.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  13.  *
  14.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  15.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
  16.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE
  17.  * POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN
  18.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19.  *
  20.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  21.  */
  22. /*
  23.  * cmapfog.c
  24.  *
  25.  * this sample code shows how to do depthcueing using fog in OpenGL with
  26.  * color index mode.  you can use the arrow keys to adjust the start and 
  27.  * end of the fog effect, the up-arrow key increments that FOG_START value, 
  28.  * the down-arrow key decrements FOG_START.  the left arrow key increments the
  29.  * FOG_END value, the righ-arrow decrements it.  The 'q' key queries the
  30.  * current FOG_START and FOG_END values.  as usual, the 'Esc' key will
  31.  * exit.  it should help give you an idea as to how the start and end values
  32.  * for fog will affect your scene as well as how to set up a color ramp
  33.  * and get OpenGL to index into it correctly.  the default color ramp
  34.  * is 32 entries wide
  35.  */
  36.  
  37. #include <GL/glx.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <X11/keysym.h>
  41.  
  42.  
  43. /*
  44.  * double buffered, color index visual attributes
  45.  */
  46. static int CIattributes[] = {
  47.     GLX_DEPTH_SIZE, 1,
  48.     GLX_DOUBLEBUFFER,
  49.     None,
  50. };
  51.  
  52. /*
  53.  * global stuff 
  54.  */
  55. #define COLOR_OFFSET    97
  56.  
  57. float MY_FOG_START = 0.0;
  58. float MY_FOG_END = 20.0;
  59.  
  60. static long W = 700, H = 700;
  61. static long size, mode;
  62.  
  63. Display *dpy;
  64. Window window;
  65.  
  66. int rampSize = 32;     /* default ramp size, 32 entries */
  67.  
  68. /*
  69.  * this routine does the actual drawing
  70.  */
  71. static void DoDisplay(void)
  72. {
  73.     GLint i, n;
  74.  
  75.    /*
  76.     * enable z buffer depth test
  77.     */
  78.     glEnable(GL_DEPTH_TEST);
  79.     glDepthRange(0, 0xfffff);
  80.     glDepthFunc(GL_LESS);
  81.  
  82.    /*
  83.     * set up projection matrix
  84.     */
  85.     glMatrixMode(GL_PROJECTION);
  86.     glLoadIdentity();
  87.     glOrtho(-30.0, 50.0, -10.0, 50.0, -50.0, 50.0);
  88.  
  89.    /*
  90.     * set up model view matrix
  91.     */
  92.     glMatrixMode(GL_MODELVIEW);
  93.  
  94.    /*
  95.     * just to make things interesting, push down a matrix and
  96.     * apply a 35 degree rotation on x, y & z axis so that the
  97.     * object drawn has some parts closer, some farther away
  98.     */
  99.     glPushMatrix();
  100.       glRotated(35, 1, 1, 1);
  101.  
  102.    /*
  103.     * clear buffers
  104.     */
  105.       glIndexi(0);
  106.       glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  107.  
  108.     /*
  109.      * now, turn on fog, linear fog, set fog start & end values as
  110.      * well as color index to the start of the ramp.
  111.      */
  112.       glEnable(GL_FOG);
  113.       glFogi(GL_FOG_MODE, GL_LINEAR);
  114.  
  115.     /*
  116.      * set GL_FOG_INDEX to the rampSize - 1. this is because say we
  117.      * have 32 entries in our ramp, the fragment color index will be
  118.      * in the range 0 - 31.
  119.      */
  120.       glFogi(GL_FOG_INDEX, rampSize-1);
  121.  
  122.       glFogf(GL_FOG_START, MY_FOG_START);
  123.       glFogf(GL_FOG_END, MY_FOG_END);
  124.   
  125.  
  126.     /*
  127.      * set color to first color in the ramp, the color of our object
  128.      */
  129.       glIndexi(COLOR_OFFSET);
  130.  
  131.       glFrontFace(GL_CW);
  132.  
  133.     /*
  134.      * draw a wire-frame pyramid
  135.      */
  136.       glBegin(GL_LINE_LOOP);
  137.          glVertex3f(0,0,0); 
  138.          glVertex3f(40,0,0); 
  139.          glVertex3f(20,40,0); 
  140.       glEnd();
  141.   
  142.       glBegin(GL_LINE_LOOP);
  143.          glVertex3f(0,0,-40); 
  144.          glVertex3f(40,0,-40); 
  145.          glVertex3f(20,40,0); 
  146.         glEnd();
  147.   
  148.       glBegin(GL_LINE_LOOP);
  149.          glVertex3f(0,0,0); 
  150.          glVertex3f(0,0,-40); 
  151.          glVertex3f(20,40,0); 
  152.       glEnd();
  153.   
  154.       glBegin(GL_LINE_LOOP);
  155.          glVertex3f(40,0,0); 
  156.          glVertex3f(40,0,-40); 
  157.          glVertex3f(20,40,0); 
  158.       glEnd();
  159.   
  160.       glFlush();
  161.     glPopMatrix();
  162.  
  163.    /*
  164.     * let's see what we did...
  165.     */
  166.     glXSwapBuffers(dpy, window);
  167.  
  168.   }
  169.  
  170. /*
  171.  * convenience function, waits for a window to map 
  172.  * so that we don't try to render into a window that
  173.  * hasn't mapped yet.
  174.  */
  175. static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
  176. {
  177.     if ((e->type == MapNotify) && (e->xmap.window == (Window)arg)) {
  178.     return GL_TRUE;
  179.     }
  180.     return GL_FALSE;
  181. }
  182.  
  183.  
  184.  
  185.  
  186. /*
  187.  * main routine
  188.  */
  189. int main(long argc, char** argv)
  190. {
  191.     XVisualInfo *vi;
  192.     Colormap cmap;
  193.     XSetWindowAttributes swa;
  194.     GLXContext cx;
  195.     XEvent event;
  196.     GLboolean needDisplay;
  197.     int i;
  198.     XColor *xc;
  199.     float numEnt;
  200.  
  201.  
  202.  
  203. /*
  204.  * print out instructions
  205.  */
  206.     fprintf(stderr, "\n cmapfog valid commands: ");
  207.     fprintf(stderr, "\n      up-arrow   : increment FOG_START ");
  208.     fprintf(stderr, "\n      down-arrow : decrement FOG_START ");
  209.     fprintf(stderr, "\n      left-arrow : increment FOG_END ");
  210.     fprintf(stderr, "\n      right-arrow: decrement FOG_END ");
  211.     fprintf(stderr, "\n      'q' key    : query current fog start and end values");
  212.     fprintf(stderr, "\n      'Esc' key  : exit ");
  213.  
  214.     fprintf(stderr, "\n ");
  215.  
  216.  
  217. /*
  218.  * if a ramp size has been entered on the command line,
  219.  * use it, else default to 32 entries
  220.  */
  221.     if (argc > 1)
  222.         rampSize = atoi(argv[1]);
  223.     else {
  224.         fprintf(stderr, "\n  using default cmap ramp size of 32.");
  225.         fprintf(stderr, "\n  to specify ramp size, run:");
  226.     fprintf(stderr, "\n      cmapfog <ramp size>"); 
  227.         }
  228.  
  229.     if ((rampSize < 1) || (rampSize > 128)) {
  230.         fprintf(stderr, "\n number of color ramp entries must be between 1 - 128\n");
  231.         exit(-1);
  232.         }
  233.  
  234. fprintf(stderr, "\n ramp size: %d", rampSize);
  235.  
  236.  
  237.   /*
  238.    * connect to display
  239.    */
  240.     dpy = XOpenDisplay(0);
  241.     if (!dpy) {
  242.     fprintf(stderr, "Can't connect to display \"%s\"\n", getenv("DISPLAY"));
  243.     return -1;
  244.     }
  245.  
  246.  
  247.   /*
  248.    * find appropriate visual
  249.    */
  250.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), CIattributes);
  251.     if (!vi) {
  252.     fprintf(stderr, "No appropriate visual on \"%s\"\n",
  253.         getenv("DISPLAY"));
  254.     return -1;
  255.     }
  256.  
  257.  
  258.   /*
  259.    * create a colormap for our window
  260.    */
  261.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual,
  262.                AllocAll);
  263.  
  264.   /*
  265.    * set up attributes and create window
  266.    */
  267.     swa.border_pixel = 0;
  268.     swa.colormap = cmap;
  269.     swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask
  270.     | KeyReleaseMask;
  271.     window = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 10, 10,
  272.                W, H,
  273.                0, vi->depth, InputOutput, vi->visual,
  274.                CWBorderPixel|CWColormap|CWEventMask, &swa);
  275.  
  276.    /*
  277.     * need a gl context to render into. don't forget to make it current!
  278.     */
  279.     cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
  280.     if (!glXMakeCurrent(dpy, window, cx)) {
  281.     fprintf(stderr, "Can't make window current to context\n");
  282.     return -1;
  283.     }
  284.  
  285.  
  286.    /*
  287.     * now for the color ramp.  allocate an array of XColor cells and
  288.     * fill them in.
  289.     */
  290.     xc = (XColor *) malloc(sizeof(XColor) * rampSize);
  291.     numEnt = (float) (rampSize-1);
  292.  
  293.     for (i = 0; i < rampSize; i++) {
  294.  
  295.         /* black to white ramp */
  296.  
  297.             xc[i].pixel = i + COLOR_OFFSET;
  298.             xc[i].red = (unsigned short) (65535.0 - (65535.0 * (i / numEnt)));
  299.             xc[i].green = (unsigned short) (65535.0 - (65535.0 * (i / numEnt)));
  300.             xc[i].blue = (unsigned short) (65535.0 - (65535.0 * (i / numEnt)));
  301.             xc[i].flags = DoRed | DoGreen | DoBlue;
  302.     }
  303.  
  304.   /*
  305.    * store ramp into window colormap
  306.    */
  307.     XStoreColors(dpy, cmap, xc, rampSize);
  308.  
  309.   /*
  310.    * tell the window manager to install this colormap for our window
  311.    */
  312.     XSetWMColormapWindows(dpy, window, &window, 1);
  313.  
  314.   /*
  315.    * map window and wait for it to map
  316.    */
  317.     XMapWindow(dpy, window);
  318.     XIfEvent(dpy, &event, WaitForMapNotify, (char*)window);
  319.  
  320.     needDisplay = GL_TRUE;
  321.  
  322.   /*
  323.    * now watch for X events 
  324.    */
  325.     for (;;) {
  326.     do {
  327.         XNextEvent(dpy, &event);
  328.         switch (event.type) {
  329.  
  330.           case Expose:
  331.         needDisplay = GL_TRUE;
  332.         break;
  333.  
  334.           case ConfigureNotify:
  335.         W = event.xconfigure.width;
  336.         H = event.xconfigure.height;
  337.         needDisplay = GL_TRUE;
  338.         break;
  339.  
  340.           case KeyPress:
  341.         {
  342.             char buf[100];
  343.             int rv;
  344.             KeySym ks;
  345.  
  346.             rv = XLookupString(&event.xkey, buf, sizeof(buf), &ks, 0);
  347.             switch (ks) {
  348.  
  349.                       case XK_Up:
  350.                         MY_FOG_START++;
  351.             if (MY_FOG_START == MY_FOG_END) {
  352.                             MY_FOG_START--;
  353.                             fprintf(stderr, "\n fog start = fog end");
  354.                             }
  355.                         else {
  356.                         needDisplay = GL_TRUE;
  357.                             fprintf(stderr, "\n fog start: %f", MY_FOG_START);
  358.                              }
  359.                         break;;
  360.  
  361.                       case XK_Down:
  362.                         MY_FOG_START--;
  363.                     needDisplay = GL_TRUE;
  364.                         fprintf(stderr, "\n fog start: %f", MY_FOG_START);
  365.                         break;;
  366.  
  367.                       case XK_Left:
  368.                         MY_FOG_END++;
  369.                     needDisplay = GL_TRUE;
  370.                         fprintf(stderr, "\n fog end: %f", MY_FOG_END);
  371.                         break;
  372.  
  373.                       case XK_Right:
  374.                         MY_FOG_END--;
  375.              if (MY_FOG_END == MY_FOG_START) {
  376.                             MY_FOG_END++;
  377.                             fprintf(stderr, "\n fog end = fog start");
  378.                             }
  379.                         else {
  380.                             fprintf(stderr, "\n fog end: %f", MY_FOG_END);
  381.                         needDisplay = GL_TRUE;
  382.                             }
  383.                         break;
  384.  
  385.               case XK_Q:
  386.               case XK_q:
  387.                          fprintf(stderr, "\n\n current fog start: %f", MY_FOG_START);
  388.                          fprintf(stderr, " current fog end: %f\n", MY_FOG_END);
  389.                          break;
  390.             
  391.               case XK_Escape:
  392.             fprintf(stderr, "\n bye...\n");
  393.             return 0;
  394.                         break;
  395.             }
  396.         }
  397.         break;
  398.         }
  399.     } while (XPending(dpy) != 0);
  400.  
  401.       /*
  402.        * redisplay if needed
  403.        */
  404.     if (needDisplay) {
  405.         needDisplay = GL_FALSE;
  406.         DoDisplay();
  407.     }
  408.     }
  409. }
  410.